class_name  Tetromino
extends Node2D
#本节点就是具体的被实例化的方块节点


var rotation_index = 0
var wall_kicks
var tetromino_data
var tetromino_cells
var is_next_piece 
var piece_container = []
var other_tetromino:Array[Tetromino] = []
var ghost_tetromino 


var move_delay: float = 0.2  # 控制移动的频率（每次移动的间隔时间）
var move_timer: float = 0.0  # 跟踪移动时间

var bounds = {
	"min_x": -216,
	"max_x": 216,
	"max_y": 457
}

signal lock_tetromino(tetromino:Tetromino)

#上面两个指导生成的变量已经在Borad节点内部被赋值了,从Shared节点内把对应形状的信息拿出来即可
#但这个是一个真正的俄罗斯方块，也就是带有形状要求的，所以我们还需要让其组合方块，获取一下方块的属性场景
@onready var piece_scene = preload("res://Sence/piece.tscn")
@onready var timer: Timer = $Timer
@onready var ghost_tetromino_scene = preload("res://Sence/ghost_tetromino.tscn")
#生成方块类：按照传入的类型，生成指定数量的块，指定生成位置以及设置对应纹理图片
func  _ready() -> void:
	tetromino_cells = Shared.Cells[tetromino_data.piece_type]
	
	#cell内部存放了Shared内部的指导位置的变量集合，在这里生成的时候使用其方向并乘以块的大小即可产生不同形状
	for cell in tetromino_cells:
		var piece = piece_scene.instantiate() as Piece
		piece_container.append(piece)
		add_child(piece)
		
		#-------------------
		Games.add_piece_to_total(piece)
		
		piece.set_texture(tetromino_data.piece_texture)
		piece.position = cell * piece.get_size()
		
	if is_next_piece == false :
		position = tetromino_data.spawn_pos
		wall_kicks = Shared.wall_kicks_i if tetromino_data.piece_type == Shared.Tetromino.I else Shared.wall_kicks_jlostz
		ghost_tetromino = ghost_tetromino_scene.instantiate() as GhostTetromino
		ghost_tetromino.tetromino_data = tetromino_data
		get_tree().root.add_child.call_deferred(ghost_tetromino)
		hard_drop_ghost.call_deferred()
		
func hard_drop_ghost():
	var final_hard_drop_position
	var ghost_position_update = caculate_golbal_position(Vector2.DOWN, global_position)
	
	while ghost_position_update != null:
		ghost_position_update = caculate_golbal_position(Vector2.DOWN, ghost_position_update)
		if ghost_position_update != null:
			final_hard_drop_position = ghost_position_update
	
	if final_hard_drop_position != null:
		var children = get_children().filter(func (c): return c is Piece)
		
		var pieces_position = []
		
		for i in children.size():
			var piece_position = children[i].position
			pieces_position.append(piece_position)
		
		ghost_tetromino.set_ghost_tetromino_position(final_hard_drop_position, pieces_position)
	
	return final_hard_drop_position
func _input(event: InputEvent) -> void:
	
	
	#if Input.is_action_just_pressed("left"):
	if Input.is_action_just_pressed("left"):
		move(Vector2.LEFT)
	elif Input.is_action_just_pressed("right"):
		move(Vector2.RIGHT)
	elif Input.is_action_pressed("down"):
		move(Vector2.DOWN)
	elif Input.is_action_just_pressed("rotation_left"):
		rotate_tetromino(-1)
	elif Input.is_action_just_pressed("rotation_right"):
		rotate_tetromino(1)
	elif Input.is_action_just_pressed("hard_drop"):
		hard_drop()



		
func move(direciton:Vector2) ->bool:
	var new_position  = caculate_golbal_position(direciton,global_position)
	if new_position != null:
		global_position = new_position
		if direciton != Vector2.DOWN:
			hard_drop_ghost.call_deferred()
		return true
	return false
	
func caculate_golbal_position(direciton:Vector2,global_position:Vector2):
	#print(global_position + direciton + piece_container[0].get_size())
	if is_colliding_with_other_tetrominos(direciton,global_position):
		return null
	
	if !is_within_game_bounds(direciton,global_position):
		return null
	return global_position + direciton * piece_container[0].get_size()

func is_within_game_bounds(direction:Vector2,starting_global_postion:Vector2) -> bool :
	for piece in piece_container:
		var new_position = piece.position +starting_global_postion+direction *piece.get_size()
		if new_position.x < bounds.min_x or new_position.y > bounds. max_y or new_position.x > bounds.max_x :
			return false 
	return true

func is_colliding_with_other_tetrominos(direction:Vector2,starting_global_postion:Vector2):
	for tetromino in other_tetromino :
		var tetromino_pieces = tetromino.get_children().filter(func(c):return c is Piece)
		for tetromino_piece in tetromino_pieces:
			#取出其他的方块，然后和当前活动方块进行遍历比较
			for piece in piece_container:
				if starting_global_postion + piece.position + direction * piece.get_size().x == tetromino.global_position + tetromino_piece.position:
					return true 
	return false 

func rotate_tetromino(direction:int) :
	var original_rotation_index = rotation_index
	if tetromino_data.piece_type == Shared.Tetromino.O:
		return
		
	apply_rotation(direction)
	
	rotation_index = wrap(rotation_index + direction, 0 , 4)
	
	if !test_wall_kicks(rotation_index,direction):
		rotation_index = original_rotation_index
		apply_rotation(-direction)
		
	hard_drop_ghost.call_deferred()
	
func apply_rotation(direction:int):
	var rotation_martix = Shared.clockwise_rotation_matrix if direction == 1 else Shared.counter_clockwise_rotation_matrix
	#获取当前形状的矩阵信息
	var tetromoino_cells = Shared.Cells[tetromino_data.piece_type]
	
	for i in tetromino_cells.size():
		var cell = tetromino_cells[i]
		var x 
		var y 
		var coordinates = rotation_martix[0] * cell.x + rotation_martix[1] * cell.y
		tetromino_cells[i] = coordinates
	
	for i in piece_container.size():
		var piece  = piece_container[i]
		piece.position = tetromino_cells[i] * piece.get_size()
		
func test_wall_kicks(rotation_index :int ,rotation_direction:int):
	var wall_wick_index = get_wallkicks_index(rotation_index,rotation_direction)
	
	for i in wall_kicks[0].size():
		var translation = wall_kicks[wall_wick_index][i]
		if move(translation):
			return true
	return false		
	
func get_wallkicks_index(rotation_index :int ,rotation_direction:int):
	var wallkick_index = rotation_index * 2
	if rotation_direction < 0 :
		wallkick_index -= 1
	return wrap(wallkick_index,0,wall_kicks.size())
	
	

func hard_drop():
	while(move(Vector2.DOWN)):
		continue
	lock()

func lock():
	timer.stop()
	lock_tetromino.emit(self)
	set_process_input(false)
	ghost_tetromino.queue_free()
	
func _on_timer_timeout() -> void:
	var should_lock = not move(Vector2.DOWN)# Replace with function body.
	if should_lock == true :
		lock()
